package com.ddw.meedeeuh.views;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JToolBar;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.basic.BasicTabbedPaneUI;

import com.ddw.meedeeuh.presenters.EditorContainerPresenter.EditorContainerView;
import com.ddw.meedeeuh.presenters.MovieEditorPresenter.MovieEditorView;
import com.ddw.meedeeuh.shared.images.ImageManager;

@SuppressWarnings("serial")
public class EditorContainerViewImpl extends JPanel implements EditorContainerView {

	private final JTabbedPane tabs = new JTabbedPane(JTabbedPane.BOTTOM, JTabbedPane.SCROLL_TAB_LAYOUT);
	private final JButton buttonSave = new JButton("Save");
	private final JButton buttonChangeMovie = new JButton("Change Movie");
	private final JButton buttonReScrape = new JButton("Re-Scrape");

	public EditorContainerViewImpl() {
		super(new GridBagLayout());

		// Set border to match left pane
		setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));

		addToolbar();
		addTabPane();

		// Default toolbar enabled state
		setToolbarEnabled(false);
	}

	@Override
	public Component asComponent() {
		return this;
	}

	@Override
	public void addEditor(MovieEditorView editor) {
		this.tabs.addTab(editor.getName(), editor.asComponent());
		final int i = this.tabs.indexOfComponent(editor.asComponent());
		this.tabs.setTabComponentAt(i, new TabWithButton(this.tabs));
		this.tabs.setSelectedIndex(i);
	}

	@Override
	public boolean containsEditor(MovieEditorView editor) {
		return this.tabs.indexOfComponent(editor.asComponent()) != -1;
	}

	@Override
	public void setSelectedEditor(MovieEditorView editor) {
		final int i = this.tabs.indexOfComponent(editor.asComponent());
		if(i != -1) {
			this.tabs.setSelectedIndex(i);
		}
	}

	@Override
	public void removeEditor(MovieEditorView editor) {
		this.tabs.remove(editor.asComponent());
	}

	@Override
	public void addEditorChangeListener(ChangeListener listener) {
		this.tabs.addChangeListener(listener);
	}

	@Override
	public MovieEditorView getSelectedEditor() {
		final int i = this.tabs.getSelectedIndex();
		return (MovieEditorView) (i == -1 ? null : this.tabs.getComponentAt(i));
	}

	@Override
	public void setToolbarEnabled(boolean enabled) {
		this.buttonChangeMovie.setEnabled(enabled);
		this.buttonReScrape.setEnabled(enabled);
		this.buttonSave.setEnabled(enabled);
	}

	private final void addToolbar() {
		final JToolBar toolbar = new JToolBar(JToolBar.HORIZONTAL);
		toolbar.setFloatable(false);
		toolbar.setRollover(true);
		toolbar.setMargin(new Insets(5, 5, 5, 5));

		// Setup toolbar buttons
		this.buttonSave.setToolTipText("Save changes to the file system and your local database");
		this.buttonChangeMovie.setToolTipText("Attempts to change the movie this was matched against");
		this.buttonReScrape.setToolTipText("Re-Scrapes the movie from various sources");

		// Add toolbar buttons
		toolbar.add(this.buttonSave);
		toolbar.add(this.buttonChangeMovie);
		toolbar.add(this.buttonReScrape);

		final GridBagConstraints gbc = new GridBagConstraints();
		gbc.anchor = GridBagConstraints.CENTER;
		gbc.weightx = 1.0;
		gbc.gridx = gbc.gridy = 0;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.gridwidth = 2;
		gbc.insets = new Insets(0, 0, 0, 0);
		add(toolbar, gbc);
	}

	private final void addTabPane() {
		final GridBagConstraints gbc = new GridBagConstraints();
		gbc.weightx = gbc.weighty = 1.0;
		gbc.anchor = GridBagConstraints.CENTER;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.gridx = 0;
		gbc.gridy = 1;
		gbc.gridwidth = GridBagConstraints.REMAINDER;

		this.tabs.setUI(new BasicTabbedPaneUI() {

			@Override
			protected void installDefaults() {
				super.installDefaults();

				this.tabInsets = new Insets(2, 5, 2, 5);
				this.contentBorderInsets = new Insets(1, 1, 1, 1);
			}

		});
		add(this.tabs, gbc);
	}

	private static class TabWithButton extends JPanel {

		public TabWithButton(final JTabbedPane pane) {
			super(new FlowLayout(FlowLayout.LEFT, 0, 0));
			setOpaque(false);

			// Create the label
			final JLabel label = new JLabel() {

				@Override
				public String getText() {
					final int index = pane.indexOfTabComponent(TabWithButton.this);
					return index != -1 ? pane.getTitleAt(index) : null;
				}

			};
			label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
			add(label);

			// Create the close button
			final TabButton button = new TabButton();
			button.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					final int index = pane.indexOfTabComponent(TabWithButton.this);
					if(index != -1) {
						pane.removeTabAt(index);
					}
				}

			});
			add(button);
		}

	}

	private static class TabButton extends JButton {

		public TabButton() {
			super(ImageManager.get().tabClose());
			setPreferredSize(new Dimension(17, 17));
			setToolTipText("Close the tab");
			setFocusable(true);
			setBorder(BorderFactory.createEtchedBorder());
			setBorderPainted(false);
			setContentAreaFilled(false);

			addMouseListener(new MouseAdapter() {

				@Override
				public void mouseEntered(MouseEvent e) {
					TabButton.this.setContentAreaFilled(true);
				}

				@Override
				public void mouseExited(MouseEvent e) {
					TabButton.this.setContentAreaFilled(false);
				}

			});
		}

	}

}
